package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"go.uber.org/zap"
	"niu-video/app/consts"
	"niu-video/app/model"
	"niu-video/app/repository"
	"niu-video/pkg/logger"
	"niu-video/pkg/rabbitmq"
	"niu-video/pkg/redis"
	"strconv"
)

var RelationService = newRelationService()

func newRelationService() *relationService {
	return &relationService{}
}

type relationService struct {
}

func (l *relationService) Relation(request model.RelationAction, userId int64) (string, error) {
	// 查询有没有这个视频
	user := repository.UserRepository.Get(request.FollowingID)
	if user.UserID == 0 {
		return "", errors.New("该用户不存在！")
	}
	switch request.ActionType {
	case 1:
		if l.IsFollow(request.FollowingID, userId) {
			return "", errors.New("您已经取消关注过了")
		}
		// 关注
		l.relation(request.FollowingID, userId)
		return "关注成功！", nil
	case 2:
		if !l.IsFollow(request.FollowingID, userId) {
			return "", errors.New("您已经取消关注过了")
		}
		l.unRelation(request.FollowingID, userId)
		return "您已取消关注", nil
	}
	return "", nil
}

func (l *relationService) relation(followingID int64, userId int64) {
	redis.Redis.Eval(consts.LuaScript, []string{
		fmt.Sprintf("%s:%d:%d", consts.REDIS_RELATION_PREFIX, followingID, userId),
		fmt.Sprintf("%s:%d", consts.REDIS_RELATION_COUNTER_PREFIX, followingID)})

	relationMessage := model.RelationMessage{
		FollowingID: followingID,
		FollowerID:  userId,
		ActionType:  1,
	}
	relationMessageJson, err := json.Marshal(relationMessage)
	logger.LogIf(err)
	rabbit := rabbitmq.NewRabbitMQ(consts.RABBITMQ_RELATION_EXCHANGE, consts.RABBITMQ_RELATION_ROUTE, consts.RABBITMQ_RELATION_QUEUE)
	defer rabbit.Close()
	rabbit.SendMessage(rabbitmq.Message{Body: string(relationMessageJson)})
}

// IsFollow
//
//	@Description: 用于获取是否是 followingID 的粉丝
//	@receiver l
//	@param followingID 对应关注用户的id
//	@param userId 自己的id
//	@return bool
func (l *relationService) IsFollow(followingID int64, userId int64) bool {
	is := redis.Redis.Has(fmt.Sprintf("%s:%d:%d", consts.REDIS_RELATION_PREFIX, followingID, userId))
	if is {
		return is
	}
	relation := repository.RelationRepository.IsFollow(followingID, userId)
	if relation.RelationID != 0 {
		return true
	}
	return false
}
func (l *relationService) unRelation(followingID int64, userId int64) {
	res := redis.Redis.Eval(consts.UnLuaScript, []string{
		fmt.Sprintf("%s:%d:%d", consts.REDIS_RELATION_PREFIX, followingID, userId),
		fmt.Sprintf("%s:%d", consts.REDIS_RELATION_COUNTER_PREFIX, followingID)})
	if !res {
		redis.Redis.Decrement(fmt.Sprintf("%s:%d", consts.REDIS_RELATION_COUNTER_PREFIX, followingID))
	}
	relationMessage := model.RelationMessage{
		FollowingID: followingID,
		FollowerID:  userId,
		ActionType:  2,
	}
	relationMessageJson, err := json.Marshal(relationMessage)
	logger.LogIf(err)
	rabbit := rabbitmq.NewRabbitMQ(consts.RABBITMQ_RELATION_EXCHANGE, consts.RABBITMQ_RELATION_ROUTE, consts.RABBITMQ_RELATION_QUEUE)
	defer rabbit.Close()
	rabbit.SendMessage(rabbitmq.Message{Body: string(relationMessageJson)})
}

func (l *relationService) RelationCount(followingID int64) int64 {
	cntStr := redis.Redis.Get(fmt.Sprintf("%s:%d", consts.REDIS_RELATION_COUNTER_PREFIX, followingID))
	if cntStr == "" {
		return 0
	}
	cnt, err := strconv.ParseInt(cntStr, 10, 64)
	if err != nil {
		logger.ErrorString("relation", "RelationCount", err.Error())
		return 0
	}
	return cnt
}

func (r *relationService) Follow(request model.PageRequest, userId int64) (videos []model.VideoVo, err error) {

	list, err := repository.RelationRepository.GetUserFollowByPage(request.Page, request.PageSize, userId)
	if err != nil {
		logger.Error("follow", zap.String("list", "视频列表查询失败"))
		return videos, errors.New("视频列表查询失败")
	}
	videos, err = VideoService.concurrencyGetVideos(list, userId)
	if err != nil {
		logger.Error("follow", zap.String("list", "视频列表查询失败"))
		return videos, errors.New("视频列表查询失败")
	}
	return videos, nil
}
